
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/05/20
// Design Name:
// Module Name: sr_reg
// Project Name: wujian100
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// base ahb addr is 0x4001_0000  none offset
//////////////////////////////////////////////////////////////////////////////////
module iopmp_reg    #(
    parameter ADDR_W                   = 12              
    )(
    
    input                               iopmprg_clk_i        ,
    input                               iopmprg_rst_n_i      ,
    //from rm_ahb_if   
    input                               iopmprg_en_i         ,  // 总线使能信号，高电平有效
    input                               iopmprg_write_i      , // 总线读写控制信号 1:w 2:r
    input  [ADDR_W - 1 : 0]             iopmprg_addr_i       ,
    input  [31 : 0]                     iopmprg_wdat_w_i     , //寄存器写数据信号
    //from sr_check
    input                               iopmprg_access_ill_i , //非法访问标志
    input  [15 : 0]                     iopmprg_hit_i        , //非法访问的设备
    //from sr_control
    input                               iopmprg_cfgdone_i ,

    //to rm_ahb_if
    output                              iopmprg_rdy_w_o   , //寄存器准备信号，高电平有效
    output reg [31 : 0]                  iopmprg_rdat_w_o  , //存器读数据信号
    output                              iopmprg_intr_w_o  , //寄存器中断信号，高电平有效
    //to sr_control
    output reg                          iopmprg_cfgen_o   ,  //配置开始信号，高电平有效
    //to sr_check
    output [31:0]                       iopmprg_rule_o       //检查规则
);

// localparam  CFGW   = 1'b0; 
// localparam  CFGOUT = 1'b1;

localparam  RULE_REG_OFFSET     = 12'h000;
localparam  CHECKILL_REG_OFFSET = 12'h004;

reg [31:0]  rule_reg;
reg [31:0]  illegal_reg;

wire        write_rule_en;
wire        read_reg_en;
wire        read_error_en;
wire        iopmprg_cfgen;



// 配置规则检查的寄存器
assign write_rule_en = (iopmprg_en_i==1 & iopmprg_write_i == 1 & iopmprg_addr_i == RULE_REG_OFFSET);
always @(posedge iopmprg_clk_i or negedge iopmprg_rst_n_i ) begin
    if(!iopmprg_rst_n_i)
       rule_reg <= 32'd0;
    else if(write_rule_en == 1'b1)
       rule_reg <= iopmprg_wdat_w_i;
    else
       rule_reg <= rule_reg;
end

// 配置访存错误寄存器
always @(posedge iopmprg_clk_i or negedge iopmprg_rst_n_i ) begin
    if(!iopmprg_rst_n_i)
       illegal_reg        <= 32'd0;
    else if(iopmprg_access_ill_i == 1'b1)begin
       illegal_reg[15:0]  <= iopmprg_hit_i;  // 对应非法访问的设备
       illegal_reg[31:16] <= 16'h0000;
    end
    else if(read_error_en == 1'b1)     //master读取后清零
       illegal_reg        <= 32'd0;   
    else
       illegal_reg        <= illegal_reg;
end


assign iopmprg_cfgen  = (iopmprg_en_i & iopmprg_write_i);
always @(posedge iopmprg_clk_i or negedge iopmprg_rst_n_i) begin
    if(!iopmprg_rst_n_i)begin
        iopmprg_cfgen_o   <= 1'b0;
    end
    else if(iopmprg_cfgen == 1'b1)     //可以开始更新检查模块
        iopmprg_cfgen_o   <= 1'b1;
    else if(iopmprg_cfgdone_i == 1'b1) //检查模块更新完成
        iopmprg_cfgen_o   <= 1'b0;
    else
        iopmprg_cfgen_o   <= iopmprg_cfgen_o;
end


//读使能
assign read_reg_en  = (iopmprg_en_i == 1 & iopmprg_write_i == 0 & iopmprg_addr_i == RULE_REG_OFFSET);
assign read_error_en = (iopmprg_en_i==1 & iopmprg_write_i == 0 & iopmprg_addr_i == CHECKILL_REG_OFFSET);

//读取寄存器
// assign iopmprg_rdat_w_o  = read_reg_en ? (rule_reg) : (32'd0);
// assign iopmprg_rdat_w_o  = read_error_en ? (illegal_reg) : (32'd0);
assign iopmprg_rule_o = rule_reg;

always@(*)begin
//    if(!iopmprg_rst_n_i)begin
//        iopmprg_rdat_w_o      <= 'd0;
//    end
    if((iopmprg_en_i == 1'b1) && (iopmprg_write_i == 1'b0) )begin
        case (iopmprg_addr_i)
            RULE_REG_OFFSET         : iopmprg_rdat_w_o = rule_reg    ;
            CHECKILL_REG_OFFSET     : iopmprg_rdat_w_o = illegal_reg ;
            default                 : iopmprg_rdat_w_o = 'd0         ;
        endcase
    end
    else begin
        iopmprg_rdat_w_o      <= 'd0;
    end
end 



assign iopmprg_rdy_w_o  = 1'b1;
assign iopmprg_intr_w_o = 1'b0;




    
endmodule
